/* mainwin.c is part of VIP program
 * Written by J. Salvador Arias, 2010
 *      CONICET, INSUE, Instituto Miguel Lillo,
 *      Miguel Lillo 205, S.M. de Tucuman (4000)
 *      Tucuman, Argentina
 *      e-mail: jsalarias@csnat.unt.edu.ar
 *
 * VIP is a free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation and
 * Creative Commons.
 *
 * This file and the VIP program is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * To view a copy of this license, visit
 * http://creativecommons.org/licenses/GPL/2.0/
 * or send a letter to
 * Creative Commons, 171 Second Street, Suite 300,
 * San Francisco, California, 94105, USA.
 */

#include "wins.h"
#include "dialogs.h"
#include "parser.h"
#include "out.h"

#define VERSION_STRING "VIP v18 16 may 2011\nJ. Salvador Arias\nCONICET, INSUE, Tucuman, Argentina\njsalarias@csnat.unt.edu.ar\n"

typedef struct tagMAINWINDATA MAINWINDATA;
struct tagMAINWINDATA {
 GtkWidget* menuGrid;
 GtkWidget* menuRec;
 GtkWidget* menuEdit;

 GtkWidget* menuOpen;
 GtkWidget* menuFeed;
 GtkWidget* menuSaveAs;
 GtkWidget* menuOpenRes;
 GtkWidget* menuSaveRes;
 GtkWidget* menuClose;
 GtkWidget* menuSetFill;
 GtkWidget* menuCreateGrid;
 GtkWidget* menuReDoGrid;
 GtkWidget* menuDestroyGrid;
 GtkWidget* menuGridTable;
 GtkWidget* menuFilter;
 GtkWidget* menuClean;
 GtkWidget* menuRefine;
 GtkWidget* menuConsensus;
 GtkWidget* menuCleanConsensus;
 GtkWidget* menuHotMouse;
 GtkWidget* menuGeoBrowser;
 GtkWidget* menuRecEdit;

 GtkWidget* removEntry;
 GtkWidget* overlapEntry;
 GtkWidget* partEntry;
 GtkWidget* maxTimeEntry;
 GtkWidget* timeLagEntry;
 GtkWidget* lagCostEntry;

 GtkWidget* lateOverlapBox;
 GtkWidget* costFractionBox;
 GtkWidget* timeLagBox;
 GtkWidget* timeFractionBox;

 GtkWidget* buttonSearch;
 GtkWidget* buttonPrevTree;
 GtkWidget* buttonNextTree;
 GtkWidget* buttonPrevNode;
 GtkWidget* buttonNextNode;
 GtkWidget* buttonNextRec;
 GtkWidget* buttonPrevRec;
 GtkWidget* buttonCopy;
 GtkWidget* radioORRec;
 GtkWidget* radioSearchRec;
 GtkWidget* radioConsRec;

 GtkWidget* treeLabelEntry;
 GtkWidget* treeNavEntry;
 GtkWidget* costLabelEntry;
 GtkWidget* vicsLabelEntry;
 GtkWidget* removsLabelEntry;
 GtkWidget* recNavEntry;
 GtkWidget* nodeLabelEntry;

 GtkTextBuffer* logBuffer;
};

static gint OnDelete (GtkWidget* mainWin, GdkEvent* event, gpointer data);

/* --- Menu events --- */
static void OnMenuOpen (GtkMenuItem* openMenu, gpointer data);
static void OnMenuFeed (GtkMenuItem* openMenu, gpointer data);
static void OnMenuSaveAs (GtkMenuItem* saveAsMenu, gpointer data);
static void OnMenuOpenRes (GtkMenuItem* openMenu, gpointer data);
static void OnMenuSaveRes (GtkMenuItem* saveResMenu, gpointer data);
static void OnMenuClose (GtkMenuItem* closeMenu, gpointer data);
static void OnMenuQuit (GtkMenuItem* quitMenu, gpointer data);

static void OnMenuSetGrid (GtkMenuItem* gridMenu, gpointer data);
static void OnMenuSetFill (GtkMenuItem* gridMenu, gpointer data);
static void OnMenuCreateGrid (GtkMenuItem* gridMenu, gpointer data);
static void OnMenuReDoGrid (GtkMenuItem* gridMenu, gpointer data);
static void OnMenuDestroyGrid (GtkMenuItem* gridMenu, gpointer data);
static void OnMenuGridTable (GtkMenuItem* gridMenu, gpointer data);

static void OnMenuPageHeuristic (GtkMenuItem* searchMenu, gpointer data);
static void OnMenuRefine (GtkMenuItem* refineMenu, gpointer data);
static void OnMenuConsensus (GtkMenuItem* consensusMenu, gpointer data);
static void OnMenuFilter (GtkMenuItem* filterMenu, gpointer data);
static void OnMenuClean (GtkMenuItem* cleanMenu, gpointer data);
static void OnMenuCleanConsensus (GtkMenuItem* cleanMenu, gpointer data);

static void OnMenuHotCheck (GtkMenuItem* editMenu, gpointer data);
static void OnMenuRecEditCheck (GtkMenuItem* editMenu, gpointer data);
static void OnMenuGeoBrowser (GtkMenuItem* browserMenu, gpointer data);
static void OnMenuSaveLog (GtkMenuItem* saveAsMenu, gpointer data);
static void OnMenuClearLog (GtkMenuItem* saveAsMenu, gpointer data);

/* --- Other events --- */
static void OnButtonApply (GtkButton* applyButton, gpointer data);
static void OnButtonSearch (GtkButton* searchButton, gpointer data);
static void OnButtonCancel (GtkButton* cancelButton, gpointer data);
static void OnButtonPrevTree (GtkButton* prevButton, gpointer data);
static void OnButtonNextTree (GtkButton* nextButton, gpointer data);
static void OnButtonPrevNode (GtkButton* prevButton, gpointer data);
static void OnButtonNextNode (GtkButton* nextButton, gpointer data);
static void OnButtonPrevRec (GtkButton* nextButton, gpointer data);
static void OnButtonNextRec (GtkButton* prevButton, gpointer data);
static void OnButtonCopy (GtkButton* copyButton, gpointer data);
static void OnRadioRec (GtkToggleButton* button, gpointer data);
static void OnUseTime (GtkCheckButton* button, gpointer data);


/* --- Other functions --- */
static int CloseData ();
static SFLAG ApplyParams (SFLAG toPrint);
static SFLAG CheckRadioRec ();

static void DoSearch (SFLAG keep);

static MAINWINDATA mainData;
static PROGRESSSTRUCT progress;

void StartMainWindow () {
 GtkWidget* gBox;
 GtkWidget* menuBar;
 GtkWidget* menu;
 GtkAccelGroup* accelGroup;

 GtkWidget* notebook;
 GtkWidget* vBox;
 GtkWidget* hBox;
 GtkWidget* label;
 GtkWidget* separator;
 GtkWidget* button;
 gchar* text;

 GtkWidget* scrollWin;
 GtkWidget* logTab;

 gBox = gtk_vbox_new (FALSE, 0);
 mainWindow = CreateWindow ("VIP: Main Window", 30, 0, 200, 500, G_CALLBACK (OnDelete), gBox);

 /* --- Sets menues --- */
 accelGroup = gtk_accel_group_new ();
 gtk_window_add_accel_group (GTK_WINDOW (mainWindow), accelGroup);
 menuBar = gtk_menu_bar_new ();
 gtk_box_pack_start (GTK_BOX (gBox), menuBar, FALSE, TRUE, 0);
 gtk_widget_show (menuBar);
 /* File */
 menu = gtk_menu_new ();
 mainData . menuOpen = CreateMenuItem (menu, "_Open...", accelGroup, GDK_O, GDK_CONTROL_MASK, G_CALLBACK (OnMenuOpen), NULL);
 gtk_widget_set_sensitive (mainData . menuOpen, TRUE);
 mainData . menuFeed = CreateMenuItem (menu, "_Feed records...", accelGroup, GDK_X, GDK_CONTROL_MASK,
                                         G_CALLBACK (OnMenuFeed), NULL);
 gtk_widget_set_sensitive (mainData . menuFeed, FALSE);
 mainData . menuSaveAs = CreateMenuItem (menu, "Save data _as...", accelGroup, GDK_S, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                         G_CALLBACK (OnMenuSaveAs), NULL);
 gtk_widget_set_sensitive (mainData . menuSaveAs, FALSE);
 CreateMenuSeparator (menu);
 mainData . menuOpenRes = CreateMenuItem (menu, "Open _results...", accelGroup, GDK_O, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
                                          G_CALLBACK (OnMenuOpenRes), NULL);
 gtk_widget_set_sensitive (mainData . menuOpenRes, FALSE);
 mainData . menuSaveRes = CreateMenuItem (menu, "_Save results as...", accelGroup, GDK_S, GDK_CONTROL_MASK,
                                         G_CALLBACK (OnMenuSaveRes), NULL);
 gtk_widget_set_sensitive (mainData . menuSaveRes, FALSE);
 CreateMenuSeparator (menu);
 mainData . menuClose = CreateMenuItem (menu, "_Close", accelGroup, GDK_W, GDK_CONTROL_MASK, G_CALLBACK (OnMenuClose), NULL);
 gtk_widget_set_sensitive (mainData . menuClose, FALSE);
 CreateMenuSeparator (menu);
 CreateMenuItem (menu, "_Quit...", accelGroup, GDK_Q, GDK_CONTROL_MASK, G_CALLBACK (OnMenuQuit), NULL);
 AddMenuToBar (menu, "_File", menuBar);
 /* Grid */
 menu = gtk_menu_new ();
 CreateMenuItem (menu, "_Grid settings...", accelGroup, GDK_G, GDK_CONTROL_MASK, G_CALLBACK (OnMenuSetGrid), NULL);
 mainData . menuSetFill = CreateMenuItem (menu, "Set _fill in all nodes", accelGroup, GDK_I, GDK_CONTROL_MASK,
                                          G_CALLBACK (OnMenuSetFill), NULL);
 CreateMenuSeparator (menu);
 mainData . menuCreateGrid = CreateMenuItem (menu, "_Create grid", accelGroup, GDK_A, GDK_CONTROL_MASK,
                                             G_CALLBACK (OnMenuCreateGrid), NULL);
 mainData . menuReDoGrid = CreateMenuItem (menu, "_Redo grid", accelGroup, GDK_B, GDK_CONTROL_MASK,
                                             G_CALLBACK (OnMenuReDoGrid), NULL);
 CreateMenuSeparator (menu);
 mainData . menuDestroyGrid = CreateMenuItem (menu, "_Destroy grid", accelGroup, GDK_D, GDK_CONTROL_MASK,
                                              G_CALLBACK (OnMenuDestroyGrid), NULL);
 CreateMenuSeparator (menu);
 mainData . menuGridTable = CreateMenuItem (menu, "Save grid _table...", accelGroup, GDK_M, GDK_CONTROL_MASK,
                                         G_CALLBACK (OnMenuGridTable), NULL);
 gtk_widget_set_sensitive (mainData . menuReDoGrid, FALSE);
 gtk_widget_set_sensitive (mainData . menuDestroyGrid, FALSE);
 gtk_widget_set_sensitive (mainData . menuGridTable, FALSE);
 mainData . menuGrid = AddMenuToBar (menu, "_Grid", menuBar);
 gtk_widget_set_sensitive (mainData . menuGrid, FALSE);

 SETFILL (1);
 SETGRIDSIZE (2.00);
 SETGRIDMODE (VONNEUMANN_NEIGHBORS);

 /* Recons */
 menu = gtk_menu_new ();
 CreateMenuItem (menu, "_Heuristic search...", accelGroup, GDK_E, GDK_CONTROL_MASK, G_CALLBACK (OnMenuPageHeuristic), NULL);
 mainData . menuRefine = CreateMenuItem (menu, "_Refine...", accelGroup, GDK_J, GDK_CONTROL_MASK, G_CALLBACK (OnMenuRefine), NULL);
 gtk_widget_set_sensitive (mainData . menuRefine, FALSE);
 CreateMenuSeparator (menu);
 mainData . menuConsensus = CreateMenuItem (menu, "_Consensus", accelGroup, GDK_U, GDK_CONTROL_MASK, G_CALLBACK (OnMenuConsensus), NULL);
 gtk_widget_set_sensitive (mainData . menuConsensus, FALSE);
 CreateMenuSeparator (menu);
 mainData . menuFilter = CreateMenuItem (menu, "_Filter...", accelGroup, GDK_F, GDK_CONTROL_MASK, G_CALLBACK (OnMenuFilter), NULL);
 gtk_widget_set_sensitive (mainData . menuFilter, FALSE);
 mainData . menuClean = CreateMenuItem (menu, "Clea_n", accelGroup, GDK_N, GDK_CONTROL_MASK, G_CALLBACK (OnMenuClean), NULL);
 gtk_widget_set_sensitive (mainData . menuClean, FALSE);
 mainData . menuCleanConsensus = CreateMenuItem (menu, "Clean consens_us", accelGroup, GDK_U, GDK_CONTROL_MASK,
                           G_CALLBACK (OnMenuCleanConsensus), NULL);
 gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
 mainData . menuRec = AddMenuToBar (menu, "_Search", menuBar);
 gtk_widget_set_sensitive (mainData . menuRec, FALSE);


 /* Edit */
 menu = gtk_menu_new ();
 mainData . menuHotMouse = CreateMenuItemCheck (menu, "_Hot mouse (map)", accelGroup, GDK_H, GDK_CONTROL_MASK,
                                                    G_CALLBACK (OnMenuHotCheck), NULL);
 gtk_widget_set_sensitive (mainData . menuHotMouse, FALSE);
 mainData . menuRecEdit = CreateMenuItemCheck (menu, "Edit _reconstruction (tree)", accelGroup, GDK_T, GDK_CONTROL_MASK,
                                                    G_CALLBACK (OnMenuRecEditCheck), NULL);
 gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
 CreateMenuSeparator (menu);
 mainData . menuGeoBrowser = CreateMenuItem (menu, "_Georeference browser", accelGroup, GDK_R, GDK_CONTROL_MASK,
                                                    G_CALLBACK (OnMenuGeoBrowser), NULL);
 gtk_widget_set_sensitive (mainData . menuGeoBrowser, FALSE);
 CreateMenuSeparator (menu);
 CreateMenuItem (menu, "_Save log...", accelGroup, GDK_L, GDK_CONTROL_MASK, G_CALLBACK (OnMenuSaveLog), NULL);
 CreateMenuItem (menu, "_Clean log", accelGroup, GDK_K, GDK_CONTROL_MASK, G_CALLBACK (OnMenuClearLog), NULL);
 mainData . menuEdit = AddMenuToBar (menu, "_Edit", menuBar);
 gtk_widget_set_sensitive (mainData . menuEdit, FALSE);

 SETFILL (1);
 SETGRIDSIZE (2.00);

 /* --- Layout --- */
 notebook = gtk_notebook_new ();
 gtk_box_pack_start (GTK_BOX (gBox), notebook, FALSE, TRUE, 0);
 gtk_widget_show (notebook);

 /* Parameters flap */
 vBox = gtk_vbox_new (FALSE, 2);
 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vBox, gtk_label_new_with_mnemonic ("_Parameters"));
 gtk_widget_show (vBox);

 mainData . removEntry = CreateEntry ("Cost of distribution removal", GTK_BOX (vBox));
 mainData . overlapEntry = CreateEntry ("Max overlap (percent)", GTK_BOX (vBox));
 mainData . costFractionBox = gtk_check_button_new_with_mnemonic ("Use fractional _cost");
 gtk_box_pack_start (GTK_BOX (vBox), mainData . costFractionBox, TRUE, TRUE, 2);
 gtk_widget_show (mainData . costFractionBox);
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);

 mainData . lateOverlapBox = gtk_check_button_new_with_mnemonic ("Use _partial removal");
 gtk_widget_show (mainData . lateOverlapBox);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . lateOverlapBox, TRUE, TRUE, 2);
 mainData . partEntry = CreateEntry ("Cost of partial removal", GTK_BOX (vBox));
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);

 mainData . timeLagBox = gtk_check_button_new_with_mnemonic ("Use _time");
 gtk_box_pack_start (GTK_BOX (vBox), mainData . timeLagBox, TRUE, TRUE, 2);
 gtk_widget_show (mainData . timeLagBox);
 mainData . timeLagEntry = CreateEntry ("Max time lag", GTK_BOX (vBox));
 mainData . lagCostEntry = CreateEntry ("Cost after time lag", GTK_BOX (vBox));
 mainData . maxTimeEntry = CreateEntry ("Max time difference", GTK_BOX (vBox));
 mainData . timeFractionBox = gtk_check_button_new_with_mnemonic ("Use _fractional time cost");
 gtk_box_pack_start (GTK_BOX (vBox), mainData . timeFractionBox, TRUE, TRUE, 2);
 gtk_widget_show (mainData . timeFractionBox);
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);
 g_signal_connect (G_OBJECT (mainData . timeLagBox), "toggled", G_CALLBACK (OnUseTime), NULL);

 text = g_strdup_printf ("%.4f", params . costRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . removEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . costPartRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . partEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . overlap * 100);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . overlapEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . costTimeLag);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . lagCostEntry), text);
 g_free (text);
 text = g_strdup_printf ("%ld", params . timeDiff);
 gtk_entry_set_text (GTK_ENTRY (mainData . maxTimeEntry), text);
 g_free (text);
 text = g_strdup_printf ("%ld", params . timeLag);
 gtk_entry_set_text (GTK_ENTRY (mainData . timeLagEntry), text);
 g_free (text);

 hBox = gtk_hbox_new (TRUE, 2);
 gtk_box_pack_start (GTK_BOX (vBox), hBox, FALSE, TRUE, 2);
 gtk_widget_show (hBox);
 button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (OnButtonApply), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), button, FALSE, TRUE, 2);
 gtk_widget_show (button);
 button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (OnButtonCancel), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), button, FALSE, TRUE, 2);
 gtk_widget_show (button);
 mainData . buttonSearch = gtk_button_new_from_stock (GTK_STOCK_EXECUTE);
 g_signal_connect (G_OBJECT (mainData . buttonSearch), "clicked", G_CALLBACK (OnButtonSearch), NULL);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . buttonSearch, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonSearch);
 gtk_widget_set_sensitive (mainData . buttonSearch, FALSE);

 /* Reconstruction flap */
 vBox = gtk_vbox_new (FALSE, 2);
 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vBox, gtk_label_new_with_mnemonic ("_Reconstruction"));
 gtk_widget_show (vBox);
 label = gtk_label_new ("Tree navigator");
 gtk_box_pack_start (GTK_BOX (vBox), label, TRUE, TRUE, 2);
 gtk_widget_show (label);
 mainData . treeNavEntry = CreateEntry ("Trees in memory", GTK_BOX (vBox));
 mainData . treeLabelEntry = CreateEntry ("Tree", GTK_BOX (vBox));
 hBox = gtk_hbox_new (TRUE, 2);
 gtk_box_pack_start (GTK_BOX (vBox), hBox, FALSE, TRUE, 2);
 gtk_widget_show (hBox);
 mainData . buttonPrevTree = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
 g_signal_connect (G_OBJECT (mainData . buttonPrevTree), "clicked", G_CALLBACK (OnButtonPrevTree), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonPrevTree, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonPrevTree);
 mainData . buttonNextTree = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
 g_signal_connect (G_OBJECT (mainData . buttonNextTree), "clicked", G_CALLBACK (OnButtonNextTree), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonNextTree, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonNextTree);
 gtk_widget_set_sensitive (mainData . buttonPrevTree, FALSE);
 gtk_widget_set_sensitive (mainData . buttonNextTree, FALSE);
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);

 label = gtk_label_new ("Reconstruction navigator");
 gtk_box_pack_start (GTK_BOX (vBox), label, TRUE, TRUE, 2);
 gtk_widget_show (label);
 mainData . costLabelEntry = CreateEntry ("Cost", GTK_BOX (vBox));
 mainData . vicsLabelEntry = CreateEntry ("Disjunct sister pairs", GTK_BOX (vBox));
 mainData . removsLabelEntry = CreateEntry ("Nodes with removal", GTK_BOX (vBox));
 mainData . recNavEntry = CreateEntry ("Reconstructions in memory", GTK_BOX (vBox));
 hBox = gtk_hbox_new (TRUE, 2);
 gtk_box_pack_start (GTK_BOX (vBox), hBox, FALSE, TRUE, 2);
 gtk_widget_show (hBox);
 mainData . buttonPrevRec = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
 g_signal_connect (G_OBJECT (mainData . buttonPrevRec), "clicked", G_CALLBACK (OnButtonPrevRec), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonPrevRec, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonPrevRec);
 mainData . buttonNextRec = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
 g_signal_connect (G_OBJECT (mainData . buttonNextRec), "clicked", G_CALLBACK (OnButtonNextRec), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonNextRec, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonNextRec);
 mainData . buttonCopy = gtk_button_new_from_stock (GTK_STOCK_COPY);
 g_signal_connect (G_OBJECT (mainData . buttonCopy), "clicked", G_CALLBACK (OnButtonCopy), NULL);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . buttonCopy, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonCopy);
 gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
 gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
 gtk_widget_set_sensitive (mainData . buttonCopy, FALSE);
 mainData . radioORRec = gtk_radio_button_new_with_mnemonic (NULL, "_OR reconstruction");
 g_signal_connect (G_OBJECT (mainData . radioORRec), "toggled", G_CALLBACK (OnRadioRec), NULL);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . radioORRec, FALSE, TRUE, 2);
 gtk_widget_show (mainData . radioORRec);
 mainData . radioSearchRec =
    gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (mainData . radioORRec), "Reconstruction _buffer");
 g_signal_connect (G_OBJECT (mainData . radioSearchRec), "toggled", G_CALLBACK (OnRadioRec), NULL);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . radioSearchRec, FALSE, TRUE, 2);
 gtk_widget_show (mainData . radioSearchRec);
 mainData . radioConsRec =
    gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (mainData . radioORRec), "_Consensus reconstruction");
 g_signal_connect (G_OBJECT (mainData . radioConsRec), "toggled", G_CALLBACK (OnRadioRec), NULL);
 gtk_box_pack_start (GTK_BOX (vBox), mainData . radioConsRec, FALSE, TRUE, 2);
 gtk_widget_show (mainData . radioConsRec);
 gtk_widget_set_sensitive (mainData . radioORRec, FALSE);
 gtk_widget_set_sensitive (mainData . radioSearchRec, FALSE);
 gtk_widget_set_sensitive (mainData . radioConsRec, FALSE);
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);

 label = gtk_label_new ("Node navigator");
 gtk_box_pack_start (GTK_BOX (vBox), label, TRUE, TRUE, 2);
 gtk_widget_show (label);
 mainData . nodeLabelEntry = CreateEntry ("Node", GTK_BOX (vBox));
 hBox = gtk_hbox_new (TRUE, 2);
 gtk_box_pack_start (GTK_BOX (vBox), hBox, FALSE, TRUE, 2);
 gtk_widget_show (hBox);
 mainData . buttonPrevNode = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
 g_signal_connect (G_OBJECT (mainData . buttonPrevNode), "clicked", G_CALLBACK (OnButtonPrevNode), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonPrevNode, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonPrevNode);
 mainData . buttonNextNode = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
 g_signal_connect (G_OBJECT (mainData . buttonNextNode), "clicked", G_CALLBACK (OnButtonNextNode), NULL);
 gtk_box_pack_start (GTK_BOX (hBox), mainData . buttonNextNode, FALSE, TRUE, 2);
 gtk_widget_show (mainData . buttonNextNode);
 gtk_widget_set_sensitive (mainData . buttonPrevNode, FALSE);
 gtk_widget_set_sensitive (mainData . buttonNextNode, FALSE);
 separator = gtk_hseparator_new ();
 gtk_box_pack_start (GTK_BOX (vBox), separator, TRUE, TRUE, 2);
 gtk_widget_show (separator);

 gtk_entry_set_text (GTK_ENTRY (mainData . treeNavEntry), "No tree");
 gtk_entry_set_text (GTK_ENTRY (mainData . treeLabelEntry), "No tree");
 gtk_entry_set_text (GTK_ENTRY (mainData . costLabelEntry), "No grid");
 gtk_entry_set_text (GTK_ENTRY (mainData . vicsLabelEntry), "No grid");
 gtk_entry_set_text (GTK_ENTRY (mainData . removsLabelEntry), "No grid");
 gtk_entry_set_text (GTK_ENTRY (mainData . recNavEntry), "No grid");
 gtk_entry_set_text (GTK_ENTRY (mainData . nodeLabelEntry), "No tree");
 gtk_editable_set_editable (GTK_EDITABLE (mainData . treeLabelEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . costLabelEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . vicsLabelEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . removsLabelEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . nodeLabelEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . treeNavEntry), FALSE);
 gtk_editable_set_editable (GTK_EDITABLE (mainData . recNavEntry), FALSE);

 /* Log flag */
 vBox = gtk_vbox_new (FALSE, 2);
 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vBox, gtk_label_new_with_mnemonic ("_Log"));
 gtk_widget_show (vBox);

 logTab = gtk_text_view_new ();
 mainData . logBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logTab));
 gtk_text_view_set_editable (GTK_TEXT_VIEW (logTab), FALSE);
 gtk_text_buffer_set_text (mainData . logBuffer, VERSION_STRING, -1);
 scrollWin = gtk_scrolled_window_new (GTK_TEXT_VIEW (logTab) -> hadjustment, GTK_TEXT_VIEW (logTab) -> vadjustment);
 gtk_container_add (GTK_CONTAINER (scrollWin), logTab);
 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollWin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 gtk_widget_show (logTab);
 gtk_box_pack_start (GTK_BOX (vBox), scrollWin, TRUE, TRUE, 0);
 gtk_widget_show (scrollWin);

 gtk_widget_show (mainWindow);
 activeNode = NULL;
 activeTree = NULL;

 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuHotMouse), FALSE);
 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);

 progress . numBar1 = 0;
 progress . actBar1 = 0;
 progress . numBar2 = 0;
 progress . actBar2 = 0;
 progress . isActive = FALSE;
}

void OnChangeRec () {
 PHYLONODE* node;
 PHYLONODE* root;
 PHYLOTREE* tree;
 gchar* text;

 if (GETTREES == NULL) {
   gtk_entry_set_text (GTK_ENTRY (mainData . treeLabelEntry), "No tree");
   gtk_entry_set_text (GTK_ENTRY (mainData . nodeLabelEntry), "No tree");
   gtk_entry_set_text (GTK_ENTRY (mainData . treeNavEntry), "No tree");
   gtk_entry_set_text (GTK_ENTRY (mainData . costLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . vicsLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . removsLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . recNavEntry), "No grid");
   return;
 }
 tree = (PHYLOTREE*) activeTree -> data;
 node = (PHYLONODE*) activeNode -> data;
 gtk_entry_set_text (GTK_ENTRY (mainData . treeLabelEntry), tree -> name);
 gtk_entry_set_text (GTK_ENTRY (mainData . nodeLabelEntry), node -> name);
 text = g_strdup_printf ("%ld of %ld", (SINTEGER) g_list_position (GETTREES, tree -> list), GETNUMTREES);
 gtk_entry_set_text (GTK_ENTRY (mainData . treeNavEntry), text);
 g_free (text);
 if (GetGridState () == TRUE) {
   CheckRadioRec ();
   root = (PHYLONODE*) tree -> root -> data;
   text = g_strdup_printf ("%.4f", root -> rec -> cost);
   CheckRealStr (text);
   gtk_entry_set_text (GTK_ENTRY (mainData . costLabelEntry), text);
   g_free (text);
   text = g_strdup_printf ("%ld", root -> rec -> numVics);
   gtk_entry_set_text (GTK_ENTRY (mainData . vicsLabelEntry), text);
   g_free (text);
   text = g_strdup_printf ("%ld", root -> rec -> numRemovNodes);
   gtk_entry_set_text (GTK_ENTRY (mainData . removsLabelEntry), text);
   g_free (text);
   if (root -> tree -> actRec != NULL)
     text = g_strdup_printf ("%ld of %ld", (SINTEGER) g_list_position (root -> tree -> recs, root -> tree -> actRec),
                             root -> tree -> stored);
   else
     text = g_strdup_printf ("%ld", root -> tree -> stored);
   gtk_entry_set_text (GTK_ENTRY (mainData . recNavEntry), text);
   g_free (text);
 }
 else {
   gtk_entry_set_text (GTK_ENTRY (mainData . costLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . vicsLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . removsLabelEntry), "No grid");
   gtk_entry_set_text (GTK_ENTRY (mainData . recNavEntry), "No grid");
 }
}

gint OnDelete (GtkWidget* widget, GdkEvent* event, gpointer data) {
 if ((GETTREES != NULL) && (CloseData () != TRUE)) return TRUE;
 gtk_main_quit ();
 return FALSE;
}

void OnMenuOpen (GtkMenuItem* openMenu, gpointer data) {
 GtkWidget* dialog;
 gchar* fileName;
 guint timer;
 PARSINGPROGDLG* progDlg;
 SCOUNTER numOlRecs, numNuRecs, numOlSpp, numNuSpp, numOlGeoSpp, numNuGeoSpp;
 GtkTextIter endBuffer;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_OPEN,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
 CreateFileFilter ("Phylogeny in a XML file (*.xml)", "*.xml", dialog);
 CreateFileFilter ("Phylogeny in a KML (Google Earth) file (*.kml)", "*.kml", dialog);
 CreateFileFilter ("All files (*.*)", "*.*", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 gtk_widget_destroy (dialog);
 if (fileName != NULL) {
   progress . isActive = TRUE;
   progDlg = ParsingProgress (&progress);
   timer = g_timeout_add (100, UpdateParsingProgress, progDlg);
   numOlRecs = GETNUMGEOREFS;
   numOlSpp = GETNUMSPP;
   numOlGeoSpp = GetNumTermsWithGeo ();
   if (ReadFile (fileName, &progress) == TRUE) {
     gtk_widget_set_sensitive (mainData . menuFeed, TRUE);
     gtk_widget_set_sensitive (mainData . menuSaveAs, TRUE);
     gtk_widget_set_sensitive (mainData . menuClose, TRUE);
     gtk_widget_set_sensitive (mainData . menuGrid, TRUE);
     gtk_widget_set_sensitive (mainData . menuEdit, TRUE);
     gtk_widget_set_sensitive (mainData . menuHotMouse, TRUE);
     gtk_widget_set_sensitive (mainData . menuGeoBrowser, TRUE);
     OpenNewTree ();
     ChangeGeo ();
     OnChangeRec ();

     gtk_widget_set_sensitive (mainData . buttonPrevNode, TRUE);
     gtk_widget_set_sensitive (mainData . buttonNextNode, TRUE);
     if (GETNUMTREES > 1)
        gtk_widget_set_sensitive (mainData . buttonNextTree, TRUE);
     numNuRecs = GETNUMGEOREFS - numOlRecs;
     numNuSpp = GETNUMSPP - numOlSpp;
     numNuGeoSpp = GetNumTermsWithGeo () - numOlGeoSpp;
     g_string_append_printf (outLog, "\n\nFile %s read\n\n%ld new teminals added (%ld with records)\n%ld new records added",
                             fileName, numNuSpp, numNuGeoSpp, numNuRecs);
     gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
     gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
     g_string_erase (outLog, 0, -1);
   }
   progress . isActive = FALSE;
 }
 g_free (fileName);
}

void OnMenuFeed (GtkMenuItem* openMenu, gpointer data) {
 GtkWidget* dialog;
 gchar* fileName;
 SCOUNTER numOlRecs, numNuRecs, numOlGeoSpp, numNuGeoSpp;
 SFLAG state;
 guint timer;
 PARSINGPROGDLG* progDlg;
 GtkTextIter endBuffer;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Feed records from file", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_OPEN,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
 CreateFileFilter ("Vip XML file (*.xml)", "*.xml", dialog);
 CreateFileFilter ("Google Earth KML file (*.kml)", "*.kml", dialog);
 CreateFileFilter ("vNDM XYD file (*.xyd)", "*.xyd", dialog);
 CreateFileFilter ("Tab delimited text (*.txt)", "*.txt", dialog);
 CreateFileFilter ("All files (*.*)", "*.*", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 gtk_widget_destroy (dialog);
 if (fileName != NULL) {
   progress . isActive = TRUE;
   progDlg = ParsingProgress (&progress);
   timer = g_timeout_add (100, UpdateParsingProgress, progDlg);
   numOlRecs = GETNUMGEOREFS;
   numOlGeoSpp = GetNumTermsWithGeo ();
   state = FeedFile (fileName, &progress);
   numNuRecs = GETNUMGEOREFS - numOlRecs;
   if (numNuRecs > 0) {
     ChangeGeo ();
     OnChangeRec ();
     numNuGeoSpp = GetNumTermsWithGeo () - numOlGeoSpp;
     g_string_append_printf (outLog, "\n\nFile %s read\n\n%ld new records added (%ld new terms with data)",
                             fileName, numNuRecs, numNuGeoSpp);
     if (state == FALSE) {
       errorMessage = g_strdup_printf ("Unable to read all records from file: %s", fileName);
       OnError ();
     }
   }
   else if (state == FALSE) {
     errorMessage = g_strdup_printf ("Unable to read file: %s", fileName);
     OnError ();
   }
   else
     g_string_append_printf (outLog, "\n\nFile %s read\nFile without records", fileName);
   gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
   gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
   g_string_erase (outLog, 0, -1);
   progress . isActive = FALSE;
 }
 g_free (fileName);
}

void OnMenuSaveAs (GtkMenuItem* saveAsMenu, gpointer data) {
 GtkWidget* dialog;
 GtkFileFilter* xmlFilter;
 GtkFileFilter* withFilter;
 GtkFileFilter* kmlFilter;
 GtkFileFilter* xydFilter;
 GtkFileFilter* tabFilter;
 GtkFileFilter* lstFilter;
 GtkFileFilter* cllFilter;
 GtkFileFilter* phyFilter;
 GtkFileFilter* claFilter;
 GtkFileFilter* userFilter;
 gchar* fileName;
 ACTIVPROGDLG* actDlg;
 guint timer;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_SAVE,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "unitled");
 xmlFilter = CreateFileFilter ("Phylogeny in a XML file (*.xml)", "*.xml", dialog);
 kmlFilter = CreateFileFilter ("Google Earth KML file (*.kml)", "*.kml", dialog);
 withFilter = CreateFileFilter ("Only terms and nodes with data (*.xml)", "*.xml", dialog);
 xydFilter = CreateFileFilter ("vNDM file (*.xyd)", "*.xyd", dialog);
 tabFilter = CreateFileFilter ("Tad delimited text file (*.txt)", "*.txt", dialog);
 lstFilter = CreateFileFilter ("Alphabetic term list (*.txt)", "*.txt", dialog);
 cllFilter = CreateFileFilter ("Alphabetic list of collections (*.txt)", "*.txt", dialog);
 claFilter = CreateFileFilter ("Phylogeny (just cladograms) in XML (*,xml)", "*.xml", dialog);
 phyFilter = CreateFileFilter ("Phylogeny in phyloXML (*.xml)", "*.xml", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
   userFilter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
   actDlg = ActivityProgress ("Writing data");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   if (userFilter == xmlFilter) {
     fileName = CheckExtention (fileName, "xml");
     WriteXMLFile (fileName);
   }
   else if (userFilter == kmlFilter) {
     fileName = CheckExtention (fileName, "kml");
     WriteKMLFile (fileName);
   }
   else if (userFilter == xydFilter) {
     fileName = CheckExtention (fileName, "xyd");
     WriteXYDFile (fileName);
   }
   else if (userFilter == tabFilter) {
     fileName = CheckExtention (fileName, "txt");
     WriteTABTable (fileName);
   }
   else if (userFilter == lstFilter) {
     fileName = CheckExtention (fileName, "txt");
     WriteLstFile (fileName);
   }
   else if (userFilter == cllFilter) {
     fileName = CheckExtention (fileName, "txt");
     WriteCllFile (fileName);
   }
   if (userFilter == withFilter) {
     fileName = CheckExtention (fileName, "xml");
     WriteXMLWithData (fileName);
   }
   if (userFilter == phyFilter) {
     fileName = CheckExtention (fileName, "xml");
     WritePhyFile (fileName);
   }
   if (userFilter == claFilter) {
     fileName = CheckExtention (fileName, "xml");
     WriteCladoFile (fileName);
   }
   actDlg -> progressUp = FALSE;
   g_free (fileName);
 }
 gtk_widget_destroy (dialog);
}

void OnMenuOpenRes (GtkMenuItem* openMenu, gpointer data) {
 GtkWidget* dialog;
 gchar* fileName;
 guint timer;
 PARSINGPROGDLG* progDlg;
 GtkTextIter endBuffer;
 GList* navTree;
 PHYLOTREE* onTree;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_OPEN,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
 CreateFileFilter ("VIP in a XML file (*.vrx)", "*.vrx", dialog);
 CreateFileFilter ("All files (*.*)", "*.*", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 gtk_widget_destroy (dialog);
 if (fileName != NULL) {
   progress . isActive = TRUE;
   progDlg = ParsingProgress (&progress);
   timer = g_timeout_add (100, UpdateParsingProgress, progDlg);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
   if (ReadResults (fileName, &progress) == TRUE) {
     g_string_append_printf (outLog, "\n\nFile %s read", fileName);
     for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
       onTree = (PHYLOTREE*) navTree -> data;
       onTree -> actRec = onTree -> recs;
       SetRec ((GPtrArray*) onTree -> actRec -> data);
       g_string_append_printf (outLog, "\n%ld reconstructions for tree %ld", onTree -> stored, onTree -> id);
     }
     gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
     gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
     g_string_erase (outLog, 0, -1);

     gtk_widget_set_sensitive (mainData . radioSearchRec, TRUE);
     gtk_widget_set_sensitive (mainData . radioConsRec, TRUE);
     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec)) == FALSE)
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec), TRUE);
     else {
       CheckRadioRec ();
       ChangeGeo ();
       OnUpdateTree ();
       OnChangeRec ();
     }
     gtk_widget_set_sensitive (mainData . menuSaveRes, TRUE);
     gtk_widget_set_sensitive (mainData . menuRefine, TRUE);
     gtk_widget_set_sensitive (mainData . menuConsensus, TRUE);
     gtk_widget_set_sensitive (mainData . menuFilter, TRUE);
     gtk_widget_set_sensitive (mainData . menuClean, TRUE);
   }
   progress . isActive = FALSE;
 }
 g_free (fileName);
}

void OnMenuSaveRes (GtkMenuItem* saveResMenu, gpointer data) {
 GtkWidget* dialog;
 GtkFileFilter* vrxFilter;
 GtkFileFilter* userFilter;
 gchar* fileName;
 ACTIVPROGDLG* actDlg;
 guint timer;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_SAVE,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "unitled.vrx");
 vrxFilter = CreateFileFilter ("VIP Results XML file (*.vrx)", "*.vrx", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
   actDlg = ActivityProgress ("Writing results");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
   userFilter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
   if (userFilter == vrxFilter) {
     fileName = CheckExtention (fileName, "vrx");
     WriteVRXFile (fileName);
   }
   actDlg -> progressUp = FALSE;
   g_free (fileName);
 }
 gtk_widget_destroy (dialog);
}

void OnMenuClose (GtkMenuItem* closeMenu, gpointer data) {
 if (CloseData () == TRUE) {
   gtk_widget_set_sensitive (mainData . menuFeed, FALSE);
   gtk_widget_set_sensitive (mainData . menuSaveAs, FALSE);
   gtk_widget_set_sensitive (mainData . menuOpenRes, FALSE);
   gtk_widget_set_sensitive (mainData . menuSaveRes, FALSE);
   gtk_widget_set_sensitive (mainData . menuClose, FALSE);
   gtk_widget_set_sensitive (mainData . menuSetFill, TRUE);
   gtk_widget_set_sensitive (mainData . menuCreateGrid, TRUE);
   gtk_widget_set_sensitive (mainData . menuReDoGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuDestroyGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuGridTable, FALSE);
   gtk_widget_set_sensitive (mainData . menuGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuOpen, TRUE);
   gtk_widget_set_sensitive (mainData . menuConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . menuRefine, FALSE);
   gtk_widget_set_sensitive (mainData . menuFilter, FALSE);
   gtk_widget_set_sensitive (mainData . menuClean, FALSE);
   gtk_widget_set_sensitive (mainData . menuRec, FALSE);

   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . timeLagBox), FALSE);

   gtk_widget_set_sensitive (mainData . buttonSearch, FALSE);

   gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonCopy, FALSE);

   gtk_widget_set_sensitive (mainData . radioORRec, FALSE);
   gtk_widget_set_sensitive (mainData . radioSearchRec, FALSE);
   gtk_widget_set_sensitive (mainData . radioConsRec, FALSE);

   gtk_widget_set_sensitive (mainData . buttonPrevTree, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextTree, FALSE);
   gtk_widget_set_sensitive (mainData . buttonPrevNode, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextNode, FALSE);

   gtk_widget_set_sensitive (mainData . menuEdit, FALSE);
   gtk_widget_set_sensitive (mainData . menuHotMouse, FALSE);
   gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
   gtk_widget_set_sensitive (mainData . menuGeoBrowser, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuHotMouse), FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);

   activeNode = NULL;
   ChangeGeo ();
   OnChangeTree (NULL);
   OnChangeRec ();

   gtk_text_buffer_set_text (mainData . logBuffer, VERSION_STRING, -1);
 }
}

void OnMenuQuit (GtkMenuItem* quitMenu, gpointer data) {
 if ((GETTREES != NULL) && (CloseData () != TRUE)) return;
 gtk_main_quit ();
}

void OnMenuSetGrid (GtkMenuItem* gridMenu, gpointer data) {
 GRIDDIALOG* gridDialog;
 gchar* entry;
 SINTEGER nuFill;
 SREAL nuSize;

 gridDialog = GridDialog (GETGRIDSIZE, GETFILL, !GetGridState ());
 if ((gtk_dialog_run (GTK_DIALOG (gridDialog -> dialog)) == GTK_RESPONSE_ACCEPT) && (GetGridState () == FALSE)) {
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (gridDialog -> sizeEntry)));
   SetCommandLine (entry);
   if (GetCmdReal (&nuSize) != FALSE) {
     if (nuSize > 0) {
       SETGRIDSIZE (nuSize);
       ChangeGeo ();
     }
   }
   g_free (entry);
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (gridDialog -> fillEntry)));
   SetCommandLine (entry);
   g_free (entry);
   if (GetCmdNumber (&nuFill) != FALSE) {
     if (nuFill >= 0)
       SETFILL (nuFill);
   }
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gridDialog  -> mooreRadio)) == TRUE)
     SETGRIDMODE (MOORE_NEIGHBORS);
   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gridDialog  -> vonneRadio)) == TRUE)
     SETGRIDMODE (VONNEUMANN_NEIGHBORS);
 }
 DestroyGridDialog (gridDialog);
}

void OnMenuSetFill (GtkMenuItem* gridMenu, gpointer data) {
 GList* navTree;
 GNode* navNode;
 PHYLOTREE* tree;
 PHYLONODE* node;
 SCOUNTER i;

 for (navTree = GETTREES; navTree != NULL; navTree = g_list_next (navTree)) {
   tree = (PHYLOTREE*) navTree -> data;
   for (i = 0; i < tree -> nodeArray -> len; ++ i) {
     navNode = (GNode*) g_ptr_array_index (tree -> nodeArray, i);
     node = (PHYLONODE*) navNode -> data;
     node -> fill = 1000 + GETFILL;
   }
 }
}

void OnMenuReDoGrid (GtkMenuItem* gridMenu, gpointer data) {
 GtkWidget* dialog;
 GtkResponseType response;
 GList* navTree;
 PHYLOTREE* tree;
 ACTIVPROGDLG* actDlg;
 guint timer;

 dialog = gtk_message_dialog_new (GTK_WINDOW (mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
          "\nDo you want to recalculate the gird?\n");
 response = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if ((response == GTK_RESPONSE_OK) || (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_ACCEPT)) {
   /* Clean the consensus */
   actDlg = ActivityProgress ("Recalculating grid");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
     tree = (PHYLOTREE*) navTree -> data;
     if (tree -> recCons != NULL) {
       DestroySingleRec (tree -> recCons);
       tree -> recCons = NULL;
     }
   }
   ApplyParams (FALSE);
   CreateGrid ();
   actDlg -> progressUp = FALSE;
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
}

void OnMenuCreateGrid (GtkMenuItem* gridMenu, gpointer data) {
 GtkWidget* dialog;
 GtkResponseType response;
 GtkTextIter endBuffer;
 ACTIVPROGDLG* actDlg;
 guint timer;

 dialog = gtk_message_dialog_new (GTK_WINDOW (mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
          "\nDo you want to create a grid with %.4lf size and %ld maximum fill?\n", GETGRIDSIZE, GETFILL);
 response = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if ((response == GTK_RESPONSE_OK) || (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_ACCEPT)) {
   actDlg = ActivityProgress ("Creating grid");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   ApplyParams (TRUE);
   CreateGrid ();
   gtk_widget_set_sensitive (mainData . menuOpen, FALSE);
   gtk_widget_set_sensitive (mainData . menuFeed, FALSE);
   gtk_widget_set_sensitive (mainData . menuOpenRes, TRUE);
   gtk_widget_set_sensitive (mainData . menuCreateGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuReDoGrid, TRUE);
   gtk_widget_set_sensitive (mainData . menuDestroyGrid, TRUE);
   gtk_widget_set_sensitive (mainData . menuGridTable, TRUE);
   gtk_widget_set_sensitive (mainData . buttonSearch, TRUE);

   gtk_widget_set_sensitive (mainData . menuHotMouse, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuHotMouse), FALSE);

   gtk_widget_set_sensitive (mainData . menuRec, TRUE);

   gtk_widget_set_sensitive (mainData . radioORRec, TRUE);
   gtk_widget_set_sensitive (mainData . buttonCopy, TRUE);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);

   ActivateGrid (TRUE);
   actDlg -> progressUp = FALSE;
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();

   g_string_append_printf (outLog, "\n\n\nGrid created, %.4f size, %ld maximum fill", GETGRIDSIZE, GETFILL);
   if (GETGRIDMODE == MOORE_NEIGHBORS)
     g_string_append (outLog, "\nMoore neighborhood (fill with Chebyshev distance)");
   else if (GETGRIDMODE == VONNEUMANN_NEIGHBORS)
     g_string_append (outLog, "\nVonNeumann neighborhood (fill with Manhattan distance)");
   g_string_append_printf (outLog, "\nOriginal records: %ld\nEffecive cells: %ld", GETNUMGEOREFS, GETNUMCELLS);
   g_string_append_printf (outLog, "\nTerms with records: %ld of %ld", GetNumTermsWithGeo (), GETNUMSPP);
   gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
   gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
   g_string_erase (outLog, 0, -1);
 }
}

void OnMenuDestroyGrid (GtkMenuItem* gridMenu, gpointer data) {
 GtkWidget* dialog;
 GtkResponseType response;
 GtkTextIter endBuffer;
 ACTIVPROGDLG* actDlg;
 guint timer;

 dialog = gtk_message_dialog_new (GTK_WINDOW (mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
          "\nDo you want to destroy actual grid (Results will be lost!)?\n");
 response = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if ((response == GTK_RESPONSE_OK) || (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_ACCEPT)) {
   actDlg = ActivityProgress ("Destroying grid");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   DestroyGrid ();
   actDlg -> progressUp = FALSE;
   ActivateGrid (FALSE);
   gtk_widget_set_sensitive (mainData . menuOpen, TRUE);
   gtk_widget_set_sensitive (mainData . menuFeed, TRUE);
   gtk_widget_set_sensitive (mainData . menuOpenRes, FALSE);
   gtk_widget_set_sensitive (mainData . menuSaveRes, FALSE);
   gtk_widget_set_sensitive (mainData . menuCreateGrid, TRUE);
   gtk_widget_set_sensitive (mainData . menuReDoGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuDestroyGrid, FALSE);
   gtk_widget_set_sensitive (mainData . menuGridTable, FALSE);
   gtk_widget_set_sensitive (mainData . buttonSearch, FALSE);

   gtk_widget_set_sensitive (mainData . menuHotMouse, TRUE);
   gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);

   gtk_widget_set_sensitive (mainData . menuConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . menuRefine, FALSE);
   gtk_widget_set_sensitive (mainData . menuFilter, FALSE);
   gtk_widget_set_sensitive (mainData . menuClean, FALSE);
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . menuRec, FALSE);

   gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonCopy, FALSE);

   gtk_widget_set_sensitive (mainData . radioORRec, FALSE);
   gtk_widget_set_sensitive (mainData . radioSearchRec, FALSE);
   gtk_widget_set_sensitive (mainData . radioConsRec, FALSE);

   OnUpdateTree ();
   OnChangeRec ();

   g_string_append_printf (outLog, "\n\nGrid destroyed, results destroyed");
   gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
   gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
   g_string_erase (outLog, 0, -1);
 }
}

void OnMenuGridTable (GtkMenuItem* gridMenu, gpointer data) {
 GtkWidget* dialog;
 GtkFileFilter* txtRichFilter;
 GtkFileFilter* kmlRichFilter;
 GtkFileFilter* txtPDFilter;
 GtkFileFilter* kmlPDFilter;
 GtkFileFilter* ndmDATFilter;
 GtkFileFilter* userFilter;
 gchar* fileName;
 ACTIVPROGDLG* actDlg;
 guint timer;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_SAVE,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "unitled.kml");
 ndmDATFilter = CreateFileFilter ("NDM matrix (*.dat)", "*.dat", dialog);
 kmlRichFilter = CreateFileFilter ("Species richness on KML (*.kml)", "*.kml", dialog);
 txtRichFilter = CreateFileFilter ("Species richness table (*.txt)", "*.txt", dialog);
 kmlPDFilter = CreateFileFilter ("Phylogenetic diversity on KML (*.kml)", "*.kml", dialog);
 txtPDFilter = CreateFileFilter ("Phylogenetic diversity table (*.txt)", "*.txt", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
   actDlg = ActivityProgress ("Writing data");
   timer = g_timeout_add (100, UpdateActivityProgress, actDlg);
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
   userFilter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
   if (userFilter == ndmDATFilter) {
     fileName = CheckExtention (fileName, "dat");
     WriteNDMMatrix (fileName);
   }
   if (userFilter == kmlRichFilter) {
     fileName = CheckExtention (fileName, "kml");
     WriteRichKMLFile (fileName);
   }
   if (userFilter == txtRichFilter) {
     fileName = CheckExtention (fileName, "txt");
     WriteSpRichness (fileName);
   }
   if (userFilter == txtPDFilter) {
     fileName = CheckExtention (fileName, "txt");
     WritePhyloDiv (fileName);
   }
   if (userFilter == kmlPDFilter) {
     fileName = CheckExtention (fileName, "kml");
     WritePDKMLFile (fileName);
   }
   actDlg -> progressUp = FALSE;
   g_free (fileName);
 }
 gtk_widget_destroy (dialog);
 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
 CheckRadioRec ();
 ChangeGeo ();
 OnUpdateTree ();
 OnChangeRec ();
}

void OnMenuPageHeuristic (GtkMenuItem* searchMenu, gpointer data) {
 SEARCHDIALOG* searchDialog;
 gchar* entry;
 SCOUNTER iters;
 SCOUNTER hold, accept;
 SFLAG keep;
 SFLAG page;
 SFLAG cons;
 SFLAG searchResponse;

 iters = 0;
 keep = FALSE;
 if (ApplyParams (TRUE) == TRUE)
   MakeOptimization (TRUE);
 searchDialog = SearchDialog ();
 searchResponse = FALSE;
 if (gtk_dialog_run (GTK_DIALOG (searchDialog -> dialog)) == GTK_RESPONSE_ACCEPT) {
   searchResponse = TRUE;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> iterEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&iters) == FALSE)
     iters = 0;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> holdEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&hold) == FALSE)
     hold = 10;
   keep = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> keepCheck));
   params . keepAll = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> allCheck));
   page = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> pageCheck));
   cons = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> consCheck));
   if (page == TRUE)
     params . algorithm = PAGE_SEARCH;
   else
     params . algorithm = FAST_SEARCH;
   if (cons == TRUE)
     params . search |= CONSTR_SEARCH;
   else
     params . search &= ~CONSTR_SEARCH;
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> flipCheck)))
     params . algorithm |= FLIP_NODES;
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> startSecRadio)))
     params . algorithm |= FIRST_SECTOR;
   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> secRadio)))
     params . algorithm |= FULL_SECTOR;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> secSizeEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&params . sectSize) == FALSE)
     params . sectSize = 20;
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> blindAnnealRadio)))
     params . algorithm |= BLIND_ANNEAL;
   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> gibbsAnnealRadio)))
     params . algorithm |= GIBBS_ANNEAL;
   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (searchDialog -> nixonAnnealRadio)))
     params . algorithm |= NIXON_ANNEAL;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> generationEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&params . generations) == FALSE)
     params . generations = 1000;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> holdEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&hold) == FALSE)
     hold = 10;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (searchDialog -> equalEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&accept) == FALSE)
     accept = 10;
   if (iters <= 0) return;
   params . its = iters;
   params . hold = 10;
   if (hold >= 1)
     params . hold = hold;
   params . acceptEqual = 50;
   if ((accept > 0) && (accept <= 100))
     params . acceptEqual = accept;
 }
 DestroySearchDialog (searchDialog);
 if (searchResponse == TRUE)
   DoSearch (keep);
}

void OnMenuRefine (GtkMenuItem* searchMenu, gpointer data) {
 REFINEDIALOG* refineDialog;
 SFLAG response;
 gchar* entry;
 SCOUNTER hold;
 SFLAG page;
 SFLAG cons;
 SFLAG fuse;
 REFINEPROGDLG* progDlg;
 guint timer;
 GtkTextIter endBuffer;
 GTimeVal actTime;
 SINTEGER totalTime;
 GList* navTree;

 if (ApplyParams (TRUE) == TRUE)
   MakeOptimization (TRUE);
 refineDialog = RefineDialog ();
 response = FALSE;
 if (gtk_dialog_run (GTK_DIALOG (refineDialog -> dialog)) == GTK_RESPONSE_ACCEPT) {
   response = TRUE;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (refineDialog -> holdEntry)));
   SetCommandLine (entry);
   if (GetCmdNumber (&hold) == FALSE)
     hold = 100;
   page = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (refineDialog -> pageCheck));
   cons = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (refineDialog -> consCheck));
   fuse = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (refineDialog -> fuseRadio));
   if (page == TRUE)
     params . algorithm = PAGE_SEARCH;
   else
     params . algorithm = FAST_SEARCH;
   if (cons == TRUE)
     params . search |= CONSTR_SEARCH;
   else
     params . search &= ~CONSTR_SEARCH;
   if (fuse == TRUE)
     params . algorithm |= REC_FUSING;
   else
     params . search &= ~REC_FUSING;
   if (hold >= 1)
     params . maxHold = hold;
   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (refineDialog -> flipCheck)))
     params . algorithm |= FLIP_NODES;
 }
 DestroyRefineDialog (refineDialog);

 if (response != TRUE) return;
 RemoveAlloSets ();
 progress . numBar1 = GETNUMTREES;
 progress . isActive = TRUE;
 progDlg = RefineProgress (&progress, TRUE);
 timer = g_timeout_add (100, UpdateRefineProgress, progDlg);
 g_string_append (outLog,"\n\n------ > Refining < ------\n\n");
 if (params . algorithm & PAGE_SEARCH)
   g_string_append (outLog,"Using Page\'s heuristics");
 else if (params . algorithm & FAST_SEARCH)
   g_string_append (outLog, "Using simple Hill climbing heuristic");
 if (params . algorithm & FLIP_NODES)
   g_string_append (outLog,"\nFlipping nodes");
 else
   g_string_append (outLog, "\nRemoving nodes");
 if (params . search & CONSTR_SEARCH)
   g_string_append (outLog,"\nConstraining to OR reconstruction");
 if (params . algorithm & REC_FUSING)
   g_string_append (outLog,"\nFusing reconstructions");
 g_get_current_time (&actTime);
 totalTime = actTime . tv_sec;
 SetConstrains (params . search && CONSTR_SEARCH);
 RefineRecs (&progress);
 SetConstrains (FALSE);
 g_get_current_time (&actTime);
 totalTime = actTime . tv_sec - totalTime;
 g_string_append_printf (outLog,"\n\nTime used on search: %ldh:%ldm:%lds", totalTime / 3600, (totalTime / 60) % 60, totalTime % 60);
 progress . isActive = FALSE;
 gtk_widget_set_sensitive (mainData . radioSearchRec, TRUE);
 gtk_widget_set_sensitive (mainData . radioConsRec, TRUE);
 for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree))
   SetTreeBestScore ((PHYLOTREE*) navTree -> data);
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec)) == FALSE)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec), TRUE);
 else {
   CheckRadioRec ();
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
 gtk_widget_set_sensitive (mainData . menuSaveRes, TRUE);
 gtk_widget_set_sensitive (mainData . menuConsensus, TRUE);
 gtk_widget_set_sensitive (mainData . menuRefine, TRUE);
 gtk_widget_set_sensitive (mainData . menuFilter, TRUE);
 gtk_widget_set_sensitive (mainData . menuClean, TRUE);
 gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);

 gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
 gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
 g_string_erase (outLog, 0, -1);
}

void OnMenuConsensus (GtkMenuItem* consensusMenu, gpointer data) {
 GList* navTree;
 PHYLOTREE* tree;

 RemoveAlloSets ();
 for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
   tree = (PHYLOTREE*) navTree -> data;
   if (tree -> recCons != NULL) {
     DestroySingleRec (tree -> recCons);
     tree -> recCons = NULL;
   }
 }
 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioConsRec), TRUE);
 gtk_widget_set_sensitive (mainData . menuCleanConsensus, TRUE);
}

void OnMenuClean (GtkMenuItem* cleanMenu, gpointer data) {
 GList* navTree;
 PHYLOTREE* tree;
 GtkTextIter endBuffer;
 GtkWidget* dialog;
 GtkResponseType response;

 dialog = gtk_message_dialog_new (GTK_WINDOW (mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
          "\nDo you want to clean reconstruction buffer (Results will be lost!)?\n");
 response = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if ((response == GTK_RESPONSE_OK) || (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_ACCEPT)) {
   RemoveAlloSets ();
   for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
     tree = (PHYLOTREE*) navTree -> data;
     if (tree -> recs != NULL) {
       DestroyRecList (tree -> recs);
       tree -> recs = NULL;
     }
     tree -> actRec = NULL;
     tree -> stored = 0;
     if (tree -> recCons != NULL) {
       DestroySingleRec (tree -> recCons);
       tree -> recCons = NULL;
     }
   }
   gtk_widget_set_sensitive (mainData . menuSaveRes, FALSE);
   gtk_widget_set_sensitive (mainData . menuConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
   gtk_widget_set_sensitive (mainData . radioSearchRec, FALSE);
   gtk_widget_set_sensitive (mainData . radioConsRec, FALSE);
   gtk_widget_set_sensitive (mainData . menuFilter, FALSE);
   gtk_widget_set_sensitive (mainData . menuRefine, FALSE);
   gtk_widget_set_sensitive (mainData . menuClean, FALSE);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
   gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);

   g_string_append_printf (outLog, "\n\nResults destroyed, only OR reconstruction keeped");
   gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
   gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
   g_string_erase (outLog, 0, -1);
 }
}

void OnMenuCleanConsensus (GtkMenuItem* cleanMenu, gpointer data) {
 GList* navTree;
 PHYLOTREE* tree;

 GtkWidget* dialog;
 GtkResponseType response;

 dialog = gtk_message_dialog_new (GTK_WINDOW (mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
          "\nDo you want to clean consensus?\n");
 response = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if ((response == GTK_RESPONSE_OK) || (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_ACCEPT)) {
   for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
     tree = (PHYLOTREE*) navTree -> data;
     if (tree -> recCons != NULL) {
       DestroySingleRec (tree -> recCons);
       tree -> recCons = NULL;
     }
     SetRec (tree -> recOR);
   }
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);
   CheckRadioRec ();
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
}

void OnMenuFilter (GtkMenuItem* filterMenu, gpointer data) {
 ENTRYDIALOG* radiusDialog;
 GtkTextIter endBuffer;
 gchar* entry;
 SREAL extra;

 radiusDialog = CounterEntryDialog (GTK_WINDOW (mapWindow), 0.00, "Filter", "Extra cost");
 if (gtk_dialog_run (GTK_DIALOG (radiusDialog -> dialog)) == GTK_RESPONSE_ACCEPT) {
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (radiusDialog -> entry)));
   SetCommandLine (entry);
   g_free (entry);
   if (GetCmdReal (&extra) != FALSE) {
     if (extra >= 0) {
       g_string_append_printf (outLog, "\n\nResults filtered");
       FilterRecs (extra);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
       gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
       gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
       g_string_erase (outLog, 0, -1);
     }
   }
 }
 DestroyEntryDialog (radiusDialog);
}

void OnMenuHotCheck (GtkMenuItem* editMenu, gpointer data) {
 SetEdition (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mainData . menuHotMouse)));
}

void OnMenuRecEditCheck (GtkMenuItem* editMenu, gpointer data) {
 SetRecEdition (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit)));
}

void OnMenuGeoBrowser (GtkMenuItem* browserMenu, gpointer data) {
 GEOREFBROWSERDLG* browser;
 PHYLONODE* node;
 GList* geoList;

 node = (PHYLONODE*) activeNode -> data;
 geoList = NULL;
 if (node -> term != NULL)
  geoList = node -> term -> firstGeo;
 if (geoList == NULL)
   geoList = GETGEOREF;
 browser = GeoRefBrowser ((GEOREF*) geoList -> data, gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mainData . menuHotMouse)));
}

void OnMenuSaveLog (GtkMenuItem* saveAsMenu, gpointer data) {
 GtkWidget* dialog;
 GtkFileFilter* txtFilter;
 gchar* fileName;
 gchar* onBuffer;
 GString* toSave;
 GtkTextIter onStart;
 GtkTextIter onEnd;

 fileName = NULL;
 dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (GETMAINWIN), GTK_FILE_CHOOSER_ACTION_SAVE,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "unitled.txt");
 txtFilter = CreateFileFilter ("Text file (*.txt)", "*.txt", dialog);
 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
   fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
   fileName = CheckExtention (fileName, "txt");
   gtk_text_buffer_get_bounds (mainData . logBuffer, &onStart, &onEnd);
   onBuffer = gtk_text_buffer_get_text (mainData .  logBuffer, &onStart, &onEnd, FALSE);
   toSave = g_string_new (onBuffer);
   WriteOutLog (fileName, toSave);
   g_free (fileName);
   g_free (onBuffer);
   g_string_free (toSave, TRUE);
 }
 gtk_widget_destroy (dialog);
}

void OnMenuClearLog (GtkMenuItem* saveAsMenu, gpointer data) {
 gtk_text_buffer_set_text (mainData . logBuffer, VERSION_STRING, -1);
}

void OnButtonApply (GtkButton* applyButton, gpointer data) {
 if ((ApplyParams (FALSE) == TRUE) && (GetGridState () == TRUE)) {
   MakeOptimization (TRUE);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
}

void OnButtonSearch (GtkButton* searchButton, gpointer data) {
 OnMenuPageHeuristic (NULL, NULL);
}

void OnButtonCancel (GtkButton* cancelButton, gpointer data) {
 gchar* text;

 text = g_strdup_printf ("%.4f", params . costPartRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . partEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . costRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . removEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . overlap);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . overlapEntry), text);
 g_free (text);
 text = g_strdup_printf ("%.4f", params . costTimeLag);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . lagCostEntry), text);
 g_free (text);
 text = g_strdup_printf ("%ld", params . timeDiff);
 gtk_entry_set_text (GTK_ENTRY (mainData . maxTimeEntry), text);
 g_free (text);
 text = g_strdup_printf ("%ld", params . timeLag);
 gtk_entry_set_text (GTK_ENTRY (mainData . timeLagEntry), text);
 g_free (text);
}

void OnButtonPrevTree (GtkButton* prevButton, gpointer data) {
 GList* nuTree;

 nuTree = g_list_previous (activeTree);
 if (nuTree != NULL) {
   ChangeGeo ();
   OnChangeTree (nuTree);
   OnChangeRec ();
   gtk_widget_set_sensitive (mainData . buttonNextTree, TRUE);
   if (g_list_previous (nuTree) == NULL)
     gtk_widget_set_sensitive (mainData . buttonPrevTree, FALSE);
 }
}

void OnButtonNextTree (GtkButton* nextButton, gpointer data) {
 GList* nuTree;

 nuTree = g_list_next (activeTree);
 if (nuTree != NULL) {
   ChangeGeo ();
   OnChangeTree (nuTree);
   OnChangeRec ();
   gtk_widget_set_sensitive (mainData . buttonPrevTree, TRUE);
   if (g_list_next (nuTree) == NULL)
     gtk_widget_set_sensitive (mainData . buttonNextTree, FALSE);
 }
}

void OnButtonPrevNode (GtkButton* prevButton, gpointer data) {
 activeNode = GetPrevNode (activeNode);
 ChangeGeo ();
 OnUpdateTree ();
 OnChangeRec ();
}

void OnButtonNextNode (GtkButton* nextButton, gpointer data) {
 activeNode = GetNextNode (activeNode);
 ChangeGeo ();
 OnUpdateTree ();
 OnChangeRec ();
}

void OnButtonPrevRec (GtkButton* nextButton, gpointer data) {
 PHYLOTREE* tree;

 tree = (PHYLOTREE*) activeTree -> data;
 tree -> actRec = g_list_previous (tree -> actRec);
 SetRec ((GPtrArray*) tree -> actRec -> data);
 gtk_widget_set_sensitive (mainData . buttonNextRec, TRUE);
 if (g_list_previous (tree -> actRec) == NULL)
   gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
 ChangeGeo ();
 OnUpdateTree ();
 OnChangeRec ();
}

void OnButtonCopy (GtkButton* copyButton, gpointer data) {
 PHYLOTREE* tree;
 GList* nuRec;

 tree = (PHYLOTREE*) activeTree -> data;
 nuRec = CopyActRec (tree);
 tree -> actRec = nuRec;
 SetRec ((GPtrArray*) tree -> actRec -> data);
 gtk_widget_set_sensitive (mainData . radioSearchRec, TRUE);
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec)) == FALSE)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec), TRUE);
 else {
   CheckRadioRec ();
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
 gtk_widget_set_sensitive (mainData . menuSaveRes, TRUE);
 gtk_widget_set_sensitive (mainData . menuConsensus, TRUE);
 gtk_widget_set_sensitive (mainData . menuRefine, TRUE);
 gtk_widget_set_sensitive (mainData . menuFilter, TRUE);
 gtk_widget_set_sensitive (mainData . menuClean, TRUE);
}

void OnButtonNextRec (GtkButton* prevButton, gpointer data) {
 PHYLOTREE* tree;

 tree = (PHYLOTREE*) activeTree -> data;
 tree -> actRec = g_list_next (tree -> actRec);
 SetRec ((GPtrArray*) tree -> actRec -> data);
 gtk_widget_set_sensitive (mainData . buttonPrevRec, TRUE);
 if (g_list_next (tree -> actRec) == NULL)
   gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
 ChangeGeo ();
 OnUpdateTree ();
 OnChangeRec ();
 gtk_widget_set_sensitive (mainData . menuSaveRes, TRUE);
}

void OnRadioRec (GtkToggleButton* button, gpointer data) {
 SFLAG change;

 change = CheckRadioRec ();
 if (change == TRUE) {
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
}

void OnUseTime (GtkCheckButton* button, gpointer data) {
 GList* navTree;
 PHYLOTREE* tree2check;

 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . timeLagBox)) == TRUE) {
   if (GETTREES == NULL) {
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . timeLagBox), FALSE);
     return;
   }
   for (navTree = GETTREES; navTree != NULL; navTree = g_list_next (navTree)) {
     tree2check = (PHYLOTREE*) navTree -> data;
     if ((tree2check -> maxTreeAge == NO_AGE) || (tree2check -> maxTreeAge == 0)) {
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . timeLagBox), FALSE);
       return;
     }
   }
 }
}

int CloseData () {
 GtkWidget* dialog;
 gint ret;

 dialog = gtk_message_dialog_new (GTK_WINDOW (GETMAINWIN), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
                                  "\nClose actual data?\n");
 ret = gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);
 if (ret != GTK_RESPONSE_YES) return FALSE;
 DestroyGrid ();
 DestroyBioGeo ();

 return TRUE;
}

SFLAG ApplyParams (SFLAG toPrint) {
 gchar* entry;
 gchar* text;
 SREAL nu;
 SFLAG change, prevMode;
 SINTEGER nuInt;
 GtkTextIter endBuffer;

 change = FALSE;
 prevMode = params . mode;
 params . mode = USE_INTS;
 params . search = NORMAL_SEARCH;

 entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . partEntry)));
 SetCommandLine (entry);
 g_free (entry);
 g_string_append_printf (outLog, "\n");
 if (GetCmdReal (&nu) != FALSE) {
   if ((nu >= 0) && (nu != params . costPartRemov)) {
     params . costPartRemov = nu;
     change = TRUE;
  }
 }
 g_string_append_printf (outLog, "\nPartial elimination set to %.4f", params . costPartRemov);
 text = g_strdup_printf ("%.4f", params . costPartRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . partEntry), text);
 g_free (text);

 entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . removEntry)));
 SetCommandLine (entry);
 g_free (entry);
 if (GetCmdReal (&nu) != FALSE) {
   if (nu < 1.00000000)
     nu = 0;
   if (nu != params . costRemov) {
     params . costRemov = nu;
     change = TRUE;
   }
 }
 g_string_append_printf (outLog, "\nDistribution eliminiation set to %.4f", params . costRemov);
 text = g_strdup_printf ("%.4f", params . costRemov);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . removEntry), text);
 g_free (text);

 entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . overlapEntry)));
 SetCommandLine (entry);
 g_free (entry);
 if (GetCmdReal (&nu) != FALSE) {
   if ((nu >= 0) && (nu < 100) && ((nu / 100) != params . overlap)) {
     params . overlap = nu / 100;
     change = TRUE;
   }
 }
 g_string_append_printf (outLog, "\nOverlap set to %.4f", params . overlap * 100);
 text = g_strdup_printf ("%.4f", params . overlap * 100);
 CheckRealStr (text);
 gtk_entry_set_text (GTK_ENTRY (mainData . overlapEntry), text);
 g_free (text);

 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . costFractionBox)) == TRUE) {
   params . mode |= OVER_REAL;
   g_string_append_printf (outLog, "\nUsing fractional cost for overlap");
 }
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . lateOverlapBox)) == TRUE) {
   params . search |= USE_LATEOVER;
   g_string_append_printf (outLog, "\nUsing partial removal");
 }

 if ((gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . timeLagBox)) == TRUE)) {
   params . mode |= USE_TIME;
   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . lagCostEntry)));
   SetCommandLine (entry);
   g_free (entry);
   g_string_append_printf (outLog, "\nUsing time");
   if (GetCmdReal (&nu) != FALSE) {
     if ((nu >= 0) && (nu != params . costTimeLag) && (nu < params . costNoVic)) {
       if ((params . mode & OVER_REAL) && ((nu + params . overlap) < params . costNoVic)) {
         params . costTimeLag = nu;
         change = TRUE;
       }
       else if (!(params . mode & OVER_REAL)) {
         params . costTimeLag = nu;
         change = TRUE;
       }
     }
   }
   text = g_strdup_printf ("%.4f", params . costTimeLag);
   CheckRealStr (text);
   gtk_entry_set_text (GTK_ENTRY (mainData . lagCostEntry), text);
   g_free (text);

   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . timeLagEntry)));
   SetCommandLine (entry);
   g_free (entry);
   if (GetCmdNumber (&nuInt) != FALSE) {
     if ((nuInt >= 0) && (nuInt != params . timeLag)) {
       params . timeLag = nuInt;
       change = TRUE;
     }
   }
   g_string_append_printf (outLog, "\nTime lag set to %ld", params . timeLag);
   if (params . timeDiff < params . timeLag)
     params . timeDiff = params . timeLag;
   text = g_strdup_printf ("%ld", params . timeLag);
   gtk_entry_set_text (GTK_ENTRY (mainData . timeLagEntry), text);
   g_free (text);

   entry = g_strdup_printf (gtk_entry_get_text (GTK_ENTRY (mainData . maxTimeEntry)));
   SetCommandLine (entry);
   g_free (entry);
   if (GetCmdNumber (&nuInt) != FALSE) {
     if ((nuInt > 0) && (nuInt != params . timeDiff) && (nuInt >= params . timeLag)) {
       params . timeDiff = nuInt;
       change = TRUE;
     }
   }
   g_string_append_printf (outLog, "\nMaximum time difference set to %ld", params . timeDiff);
   text = g_strdup_printf ("%ld", params . timeDiff);
   gtk_entry_set_text (GTK_ENTRY (mainData . maxTimeEntry), text);
   g_free (text);

   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . timeFractionBox)) == TRUE) {
     params . mode |= TIME_REAL;
     g_string_append_printf (outLog, "\nUsing fractionals cost on time");
   }
 }
 if (params . mode != prevMode)
   change = TRUE;
 if ((change == TRUE) || (toPrint == TRUE)) {
   gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
   gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
 }
 g_string_erase (outLog, 0, -1);
 return change;
}

SFLAG CheckRadioRec () {
 SFLAG change;
 PHYLOTREE* tree;
 GtkTextIter endBuffer;

 change = TRUE;
 tree = (PHYLOTREE*) activeTree -> data;
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioORRec)) == TRUE) {
   tree -> actRec = NULL;
   SetRec (tree -> recOR);
   gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
   change = TRUE;
   gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);
 }
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioConsRec)) == TRUE) {
   if (tree -> recs == NULL) {
     SetRec (tree -> recOR);
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
     return TRUE;
   }
   tree -> actRec = NULL;
   if (tree -> recCons == NULL) {
     MakeCommonBarriers ();
     gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
     gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
     g_string_erase (outLog, 0, -1);
   }
   SetRec (tree -> recCons);
   gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
   gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
   gtk_widget_set_sensitive (mainData . menuRecEdit, FALSE);
   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mainData . menuRecEdit), FALSE);
   change = TRUE;
   gtk_widget_set_sensitive (mainData . menuCleanConsensus, TRUE);
 }
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec)) == TRUE) {
   if (tree -> actRec == NULL) {
     if (tree -> recs == NULL) {
       SetRec (tree -> recOR);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
       return TRUE;
     }
     tree -> actRec = tree -> recs;
     SetRec ((GPtrArray*) tree -> actRec -> data);
     change = TRUE;
   }
   if (g_list_previous (tree -> actRec) != NULL)
     gtk_widget_set_sensitive (mainData . buttonPrevRec, TRUE);
   else
     gtk_widget_set_sensitive (mainData . buttonPrevRec, FALSE);
   if (g_list_next (tree -> actRec) != NULL)
     gtk_widget_set_sensitive (mainData . buttonNextRec, TRUE);
   else
     gtk_widget_set_sensitive (mainData . buttonNextRec, FALSE);
   gtk_widget_set_sensitive (mainData . menuRecEdit, TRUE);
 }
 return change;
}

void DoSearch (SFLAG keep) {
 GList* navTree;
 PHYLOTREE* tree;
 SEARCHPROGDLG* progDlg;
 guint timer;
 GtkTextIter endBuffer;
 GTimeVal actTime;
 SINTEGER totalTime;

 /* Clean previous recontructions */
 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioORRec), TRUE);
 for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree)) {
   tree = (PHYLOTREE*) navTree -> data;
   if (keep == FALSE) {
     if (tree -> recs != NULL) {
       DestroyRecList (tree -> recs);
       tree -> recs = NULL;
     }
     tree -> actRec = NULL;
     tree -> stored = 0;
   }
   if (tree -> recCons != NULL) {
     DestroySingleRec (tree -> recCons);
     tree -> recCons = NULL;
   }
 }
 RemoveAlloSets ();
 progress . numBar1 = GETNUMTREES;
 progress . numBar2 = params . its;
 progress . isActive = TRUE;
 progDlg = SearchProgress (&progress, TRUE);
 timer = g_timeout_add (100, UpdateSearchProgress, progDlg);
 g_string_append (outLog,"\n\n------ > Searching < ------\n\n");
 if (params . algorithm & PAGE_SEARCH)
   g_string_append (outLog,"Using Page\'s heuristics");
 else if (params . algorithm & FAST_SEARCH)
   g_string_append (outLog, "Using simple Hill climbing heuristic");
 if (params . algorithm & FLIP_NODES)
   g_string_append (outLog,"\nFlipping nodes");
 else
   g_string_append (outLog, "\nRemoving nodes");
 if (params . algorithm & FIRST_SECTOR)
   g_string_append_printf (outLog,"\nStarting with a sector of %ld nodes", params . sectSize);
 else if (params . algorithm & FULL_SECTOR)
   g_string_append_printf (outLog,"\nUsing sectors of %ld nodes", params . sectSize);
 if (params . algorithm & BLIND_ANNEAL)
   g_string_append_printf (outLog,"\nUsing blind annelaing (%ld generations)", params . generations);
 else if (params . algorithm & GIBBS_ANNEAL)
   g_string_append_printf (outLog,"\nUsing Gibb\'s annealing (%ld generations)", params . generations);
 else if (params . algorithm & NIXON_ANNEAL)
   g_string_append_printf (outLog,"\nUsing Nixon\'s annealing (%ld generations)", params . generations);
 if (params . search & CONSTR_SEARCH)
   g_string_append (outLog,"\nConstraining to OR reconstruction");
 g_string_append_printf (outLog, "\n%ld iterations per tree\nHolding %ld reconstructions per iteration", params . its, params . hold);
 g_get_current_time (&actTime);
 totalTime = actTime . tv_sec;
 SetConstrains (params . search && CONSTR_SEARCH);
 SearchMain (&progress);
 SetConstrains (FALSE);
 g_get_current_time (&actTime);
 totalTime = actTime . tv_sec - totalTime;
 g_string_append_printf (outLog,"\n\nTime used on search: %ldh:%ldm:%lds", totalTime / 3600, (totalTime / 60) % 60, totalTime % 60);
 progress . isActive = FALSE;
 gtk_widget_set_sensitive (mainData . radioSearchRec, TRUE);
 gtk_widget_set_sensitive (mainData . radioConsRec, TRUE);
 for (navTree = trees; navTree != NULL; navTree = g_list_next (navTree))
   SetTreeBestScore ((PHYLOTREE*) navTree -> data);
 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec)) == FALSE)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mainData . radioSearchRec), TRUE);
 else {
   CheckRadioRec ();
   ChangeGeo ();
   OnUpdateTree ();
   OnChangeRec ();
 }
 gtk_widget_set_sensitive (mainData . menuSaveRes, TRUE);
 gtk_widget_set_sensitive (mainData . menuConsensus, TRUE);
 gtk_widget_set_sensitive (mainData . menuRefine, TRUE);
 gtk_widget_set_sensitive (mainData . menuFilter, TRUE);
 gtk_widget_set_sensitive (mainData . menuClean, TRUE);
 gtk_widget_set_sensitive (mainData . menuCleanConsensus, FALSE);

 gtk_text_buffer_get_end_iter (mainData . logBuffer, &endBuffer);
 gtk_text_buffer_insert (mainData . logBuffer, &endBuffer, outLog -> str, -1);
 g_string_erase (outLog, 0, -1);
}
